package asds.map
{
	import asds.AbstractCollection;
	import asds.ICollection;
	import asds.IMap;
	import asds.ISet;
	import asds.Iterator;
	import asds.asds_namespace;
	import asds.list.ArrayList;
	import asds.sets.LinkedHashSet;

	import flash.utils.Dictionary;

	/**
	 * 与hashMap相比优点在于迭代时速度非常快,而且是有序的，使用链表维护内部次序.
	 * @author 青竹
	 * @email hui161@gmail.com
	 */
	public class LinkedHashMap extends AbstractMap //implements IMap
	{
		use namespace asds_namespace;
		asds_namespace var _head:Node;
		asds_namespace var _tail:Node;
		public function LinkedHashMap()
		{
			_keys=new Dictionary();
		}

		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function containsValue(value:Object):Boolean
		{
			for each (var p:* in _keys){
				  if(p.data===value) return true
			}
			return false;
		}

		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function get(key:Object):Object
		{
			return _keys[key].data;
		}

		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function put(key:Object, value:Object):void
		{
			var temp:Node=new Node(value);
			if(_keys.hasOwnProperty(key)) {
				_keys[key]=temp;
				return;
			}


			if(!_head){
				_tail= _head=temp;
			}else{
				_tail.next=temp;
				temp.prev=_tail;
				_tail=temp;
			}
			_keys[key]=temp;
			_size++;
			return
		}
		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function putAll(map:IMap):void
		{
			var linkedSet:ISet=map.entrySet();
			var i:Iterator=linkedSet.iterator();
			var temp:MapEntry;
			while(i.hasNext()){
				temp=MapEntry(i.next())
			    put(temp.key,temp.value);
			}
		}
		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function equals(o:*):Boolean{
			if(!(o is IMap)) return false;
			if(IMap(o).size()!=_size) return false;
			var i:Iterator=IMap(o).entrySet().iterator();
			var temp:MapEntry;
			while(i.hasNext()){
				temp=MapEntry(i.next());
				if(!_keys.hasOwnProperty(temp.key)) return false
			    if(_keys[temp.key].data!==temp.value) return false;

			}
		    return true;
		}
		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function removeByKey(key:*):*{
			if(!_keys.hasOwnProperty(key)) return null;
			var temp:Node=_keys[key];
			if(_tail==_head){
				_tail=_head=null;
				delete _keys[key];
				_size--;
				return temp.data;
			}
			if(temp==_head){
				_head.next.prev=null;
				_head= _head.next;
				delete _keys[key];
				_size--;
				return temp.data;
			}
			if(temp==_tail){
				_tail.prev.next=null;
				delete _keys[key];
				_tail=_tail.prev;
				_size--;
				return temp.data;
			}
			temp.prev.next=temp.next;
			temp.next.prev=temp.prev;
			_size--
			delete _keys[key];
			return temp.data;
		}
		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function entrySet():ISet{
			var set:ISet=new LinkedHashSet();
			for(var i:* in _keys){
				set.add(new MapEntry(i,_keys[i].data))
			}
			return set;
		}
		/**
		 *
		 * @inheritDoc
		 *
		 */
		override public function getAllValue():ICollection
		{
			var array:ArrayList=new ArrayList();
			for each (var p:* in _keys){
				array.add(p.data);
			}
			return array;
		}
		/**
		 * 对Map中的值进行迭代，HashMap的迭代速度远不如LinkedHashMap.
		 * @return
		 *
		 */
		public function iterator():LinkedHashMapIterator{
		   return new LinkedHashMapIterator(this);
		}

	}
}
